package org.ccay.audit.service.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import org.apache.commons.beanutils.BeanUtils;
import org.ccay.audit.exception.AbstractAuditor;
import org.ccay.audit.vo.LogVO;
import org.ccay.core.log.Audit;
import org.ccay.core.log.AuditContext;
import org.ccay.core.log.CcayLoggerFactory;
import org.ccay.core.log.DifAudit;
import org.ccay.core.log.ILogger;
import org.ccay.core.util.JsonUtil;
import org.ccay.core.util.StringUtil;

/**
 * 差异日志Auditor
 * @version:
 */
public class DifLogAuditor extends AbstractAuditor {
	
	private final ILogger logger = CcayLoggerFactory.getLogger(getClass());

	/* (non-Javadoc)
	 * @see org.ccay.log.IAuditor#buildMessage(org.ccay.log.AuditContext)
	 */
	public Serializable buildMessage(AuditContext context) {
		DifAudit difAudit = context.getMethod().getAnnotation(DifAudit.class);
	
		Object[] paramValues = context.getParameterValues();
	
		// 待序列化的对象
		int index = difAudit.subject();
		if(index<0 || index>=paramValues.length) {
			logger.error("The subject value of DifAudit annotation is illegal for "+context.getMethod()+" Method.");
			return null;
		}
		Object subject = paramValues[index];
		
		// objectId规则
		String objectIdExpr = difAudit.objectId();
		if(objectIdExpr.startsWith("#")) {
			objectIdExpr = objectIdExpr.substring(1);
		}
		
		// 是否是批量操作
		boolean batch = difAudit.batch();
		if(batch) {
			return buildBatchLogs(subject, objectIdExpr, context);
		} else {
			return buildLogVO(subject, objectIdExpr, context);
		}
	}
	
	/** 
	 * 创建单一的LogVO对象。
	 * 	
	 * @author chaowangbang
	 * @since Feb 29, 2012
	 * @param subject
	 * @param objectIdExpr
	 * @param context
	 * @return
	 */
	private LogVO buildLogVO(Object subject, String objectIdExpr, AuditContext context) {
		try {
			//add by zhaowei 2012-10-26
			LogVO log = buildCommonLogVO(context);
			Audit audit = context.getMethod().getAnnotation(Audit.class);
			String operationTemplate=audit.operation();//保存operation信息
			String moduleTemplate=audit.module();//保存module信息
			DefaultAuditor defaultAuditor=new DefaultAuditor();
			if(!StringUtil.isNullOrEmpty(operationTemplate)){
				String operation=defaultAuditor.convertMessage(context, operationTemplate);//转换operation中的EL表达式
				log.setOperation(operation);
			}
			if(!StringUtil.isNullOrEmpty(moduleTemplate)){
				String module=defaultAuditor.convertMessage(context, moduleTemplate);//转换module中的EL表达式
				log.setModule(module);
			}
			//end
			String message = JsonUtil.getCcayJsonString("formatLog", subject);
			log.setMessage(message);
			log.setLogType(1);
			String objectId = BeanUtils.getProperty(subject, objectIdExpr);
			log.setObjectId(objectId);
			
			//设置角色ID
			log.setDimension(context.getDimension());
			return log;
		} catch (Exception e) {
			logger.warn(e);
			return null;
		}
	}
	
	/** 
	 * 构造批量的LogVO.
	 * 	
	 * @author chaowangbang
	 * @since Mar 6, 2012
	 * @param subject
	 * @param objectIdExpr
	 * @param context
	 * @return
	 */
	private Serializable buildBatchLogs(Object subject, String objectIdExpr, AuditContext context) {
		ArrayList<LogVO> logs = new ArrayList<LogVO>();
		if(Collection.class.isAssignableFrom(subject.getClass())) {
			Collection vos = (Collection)subject;
			for(Iterator iter = vos.iterator(); iter.hasNext();) {
				try {
					Object object = iter.next();
					
					LogVO log = buildLogVO(object, objectIdExpr, context);
					if(log!=null) {
						logs.add(log);
					}
				} catch (Exception e) {
					logger.warn(e);
				}
			}
		}
		
		return logs;
	}

}
